home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / ATMOSPH.C next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  45.8 KB  |  2,481 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                   atmosph.c
  3. *
  4. *  This module contains all functions for atmospheric effects.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "atmosph.h"
  28. #include "colour.h"
  29. #include "povray.h"
  30. #include "texture.h"
  31. #include "pigment.h"
  32. #include "objects.h"
  33. #include "lighting.h"
  34. #include "matrices.h"
  35. #include "texture.h"
  36.  
  37.  
  38.  
  39. /*****************************************************************************
  40. * Local preprocessor defines
  41. ******************************************************************************/
  42.  
  43. #define BLACK_LEVEL 0.0001
  44.  
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local typedefs
  49. ******************************************************************************/
  50.  
  51. typedef struct Light_List_Struct LIGHT_LIST;
  52.  
  53. struct Light_List_Struct
  54. {
  55.   int active;
  56.   DBL t1, t2;
  57.   LIGHT_SOURCE *Light;
  58. };
  59.  
  60.  
  61.  
  62. /*****************************************************************************
  63. * Local variables
  64. ******************************************************************************/
  65.  
  66. /*
  67.  * Atmosphere stuff.
  68.  */
  69.  
  70. /* List of active lights. */
  71.  
  72. static LIGHT_LIST *Light_List;
  73.  
  74. /* Min. and max. intersetcion depths with light source areas. */
  75.  
  76. static DBL *tmin, *tmax;
  77.  
  78.  
  79.  
  80. /*****************************************************************************
  81. * Static functions
  82. ******************************************************************************/
  83.  
  84. static DBL constant_fog PARAMS((RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour));
  85. static DBL ground_fog PARAMS((RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour));
  86.  
  87. static void supersample_atmosphere PARAMS((LIGHT_LIST *Light_List,
  88.   int level, RAY *Ray, ATMOSPHERE *Atmosphere,
  89.   DBL d1, COLOUR C1, DBL d3, COLOUR C3));
  90.  
  91. static void sample_atmosphere PARAMS((LIGHT_LIST *Light_List, DBL dist,
  92.   RAY *Ray, ATMOSPHERE *Atmosphere, COLOUR Col));
  93.  
  94. static int intersect_spotlight PARAMS((RAY *Ray, LIGHT_SOURCE *Light, DBL *d1, DBL *d2));
  95. static int intersect_cylinderlight PARAMS((RAY *Ray, LIGHT_SOURCE *Light, DBL *d1, DBL *d2));
  96.  
  97. static void do_atmospheric_scattering PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour, int Light_Ray_Flag));
  98. static void do_fog PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour, int Light_Ray_Flag));
  99. static void do_rainbow PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour));
  100. static void do_skysphere PARAMS((RAY *Ray, COLOUR Colour));
  101.  
  102.  
  103.  
  104. /*****************************************************************************
  105. *
  106. * FUNCTION
  107. *
  108. *   Initialize_Atmosphere_Code
  109. *
  110. * INPUT
  111. *
  112. * OUTPUT
  113. *
  114. * RETURNS
  115. *
  116. * AUTHOR
  117. *
  118. *   Dieter Bayer
  119. *
  120. * DESCRIPTION
  121. *
  122. *   Initialize atmosphere specific variables.
  123. *
  124. * CHANGES
  125. *
  126. *   Aug 1995 : Creation.
  127. *
  128. ******************************************************************************/
  129.  
  130. void Initialize_Atmosphere_Code()
  131. {
  132.   Light_List = NULL;
  133.  
  134.   tmin = NULL;
  135.   tmax = NULL;
  136.  
  137.   /* Allocate memory for atmosphere. */
  138.  
  139.   if ((Frame.Atmosphere != NULL) && 
  140.       (fabs(Frame.Atmosphere->Distance) > EPSILON) &&
  141.       (Frame.Number_Of_Light_Sources > 0))
  142.   {
  143.     Light_List = (LIGHT_LIST *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(LIGHT_LIST), "atmosphere sampling lists");
  144.  
  145.     tmin = (DBL *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(DBL), "atmosphere sampling lists");
  146.  
  147.     tmax = (DBL *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(DBL), "atmosphere sampling lists");
  148.   }
  149. }
  150.  
  151.  
  152.  
  153. /*****************************************************************************
  154. *
  155. * FUNCTION
  156. *
  157. *   Deinitialize_Atmosphere_Code
  158. *
  159. * INPUT
  160. *
  161. * OUTPUT
  162. *
  163. * RETURNS
  164. *
  165. * AUTHOR
  166. *
  167. *   Dieter Bayer
  168. *
  169. * DESCRIPTION
  170. *
  171. *   Deinitialize atmosphere specific variables.
  172. *
  173. * CHANGES
  174. *
  175. *   Aug 1995 : Creation.
  176. *
  177. ******************************************************************************/
  178.  
  179. void Deinitialize_Atmosphere_Code()
  180. {
  181.   /* Free memory used by atmosphere. */
  182.  
  183.   if (Light_List != NULL)
  184.   {
  185.     POV_FREE(Light_List);
  186.     POV_FREE(tmin);
  187.     POV_FREE(tmax);
  188.   }
  189.  
  190.   Light_List = NULL;
  191.  
  192.   tmin = NULL;
  193.   tmax = NULL;
  194. }
  195.  
  196.  
  197.  
  198. /*****************************************************************************
  199. *
  200. * FUNCTION
  201. *
  202. *   Do_Infinite_Atmosphere
  203. *
  204. * INPUT
  205. *
  206. *   Ray    - Current ray
  207. *
  208. * OUTPUT
  209. *
  210. *   Colour - Color of the current ray
  211. *
  212. * RETURNS
  213. *   
  214. * AUTHOR
  215. *
  216. *   Dieter Bayer
  217. *   
  218. * DESCRIPTION
  219. *
  220. *   Apply atmospheric effects to an infinite ray.
  221. *
  222. * CHANGES
  223. *
  224. *   Feb 1995 : Creation.
  225. *
  226. *   Jun 1995 : Added code for alpha channel support. [DB]
  227. *
  228. ******************************************************************************/
  229.  
  230. void Do_Infinite_Atmosphere(Ray, Colour)
  231. RAY *Ray;
  232. COLOUR Colour;
  233. {
  234.   /* Set background color. */
  235.  
  236.   Assign_Colour(Colour, Frame.Background_Colour);
  237.   
  238.   Colour[FILTER] = 0.0;
  239.   Colour[TRANSM] = 1.0;
  240.  
  241.   /* Determine atmospheric effects for infinite ray. */
  242.  
  243.   do_skysphere(Ray, Colour);
  244. }
  245.  
  246.  
  247.  
  248. /*****************************************************************************
  249. *
  250. * FUNCTION
  251. *
  252. *   Do_Finite_Atmosphere
  253. *
  254. * INPUT
  255. *
  256. *   Ray            - Current ray
  257. *   Intersection   - Current intersection
  258. *   Light_Ray_Flag - TRUE if ray is a light source ray
  259. *
  260. * OUTPUT
  261. *
  262. *   Colour         - Color of the current ray
  263. *
  264. * RETURNS
  265. *
  266. * AUTHOR
  267. *
  268. *   Dieter Bayer
  269. *
  270. * DESCRIPTION
  271. *
  272. *   Apply atmospheric effects to a finite ray.
  273. *
  274. * CHANGES
  275. *
  276. *   Feb 1995 : Creation.
  277. *
  278. ******************************************************************************/
  279.  
  280. void Do_Finite_Atmosphere(Ray, Intersection, Colour, Light_Ray_Flag)
  281. RAY *Ray;
  282. INTERSECTION *Intersection;
  283. COLOUR Colour;
  284. int Light_Ray_Flag;
  285. {
  286.   if (!Light_Ray_Flag)
  287.   {
  288.     do_rainbow(Ray, Intersection, Colour);
  289.   }
  290.  
  291.   do_atmospheric_scattering(Ray, Intersection, Colour, Light_Ray_Flag);
  292.  
  293.   do_fog(Ray, Intersection, Colour, Light_Ray_Flag);
  294. }
  295.  
  296.  
  297.  
  298. /*****************************************************************************
  299. *
  300. * FUNCTION
  301. *
  302. *   do_atmospheric_scattering
  303. *
  304. * INPUT
  305. *
  306. *   Ray            - Current ray
  307. *   Intersection   - Current intersection
  308. *   Light_Ray_Flag - TRUE if ray is a light source ray
  309. *
  310. * OUTPUT
  311. *
  312. *   Colour         - Color of the current ray
  313. *
  314. * RETURNS
  315. *
  316. * AUTHOR
  317. *
  318. *   Dieter Bayer
  319. *
  320. * DESCRIPTION
  321. *
  322. *   Simulate atmospheric scattering using volume sampling.
  323. *
  324. *   Ideas for the atmospheric scattering were taken from:
  325. *
  326. *     - M. Inakage, "An Illumination Model for Atmospheric Environments", ..
  327. *
  328. *     - Nishita, T., Miyawaki, Y. and Nakamae, E., "A Shading Model for
  329. *       Atmospheric Scattering Considering Luminous Intensity Distribution
  330. *       of Light Sources", Computer Graphics, 21, 4, 1987, 303-310
  331. *
  332. * CHANGES
  333. *
  334. *   Nov 1994 : Creation.
  335. *
  336. *   Jan 1995 : Added support of cylindrical light sources. [DB]
  337. *
  338. *   Jun 1995 : Added code for alpha channel support. [DB]
  339. *
  340. ******************************************************************************/
  341.  
  342. static void do_atmospheric_scattering(Ray, Intersection, Colour, Light_Ray_Flag)
  343. RAY *Ray;
  344. INTERSECTION *Intersection;
  345. COLOUR Colour;
  346. int Light_Ray_Flag;
  347. {
  348.   int i, j;
  349.   int active, interval, intervals, insert;
  350.   DBL k, jdist, t1, t2, f, fi;
  351.   DBL dist, dist_prev;
  352.   DBL step;
  353.   COLOUR Col_total, Col, Col_prev, Max_Colour, C1, C2;
  354.   LIGHT_SOURCE *Light;
  355.   ATMOSPHERE *Atmosphere;
  356.  
  357.   /* Why are we here? */
  358.  
  359.   if (((Atmosphere = Frame.Atmosphere) == NULL) || 
  360.       (Frame.Atmosphere->Distance == 0.0) ||
  361.       (Frame.Number_Of_Light_Sources == 0))
  362.   {
  363.     return;
  364.   }
  365.  
  366.   /*
  367.    * If we have a light source ray we only have to attenuate
  368.    * the light source color due to the distance traveled.
  369.    */
  370.  
  371.   if (Light_Ray_Flag)
  372.   {
  373.     k = exp(-Intersection->Depth / Atmosphere->Distance);
  374.  
  375.     /* Check for minimum transmittance. */
  376.  
  377.     if (k < Atmosphere->Colour[TRANSM])
  378.     {
  379.       k = Atmosphere->Colour[TRANSM];
  380.     }
  381.  
  382.     VScaleEq(Colour, k);
  383.  
  384.     return;
  385.   }
  386.  
  387.   /* Init light list and sampling intervals. */
  388.  
  389.   for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  390.   {
  391.     Light_List[i].active = FALSE;
  392.     Light_List[i].t1     = 0.0;
  393.     Light_List[i].t2     = Max_Distance;
  394.     Light_List[i].Light  = NULL;
  395.  
  396.     tmin[i] =  BOUND_HUGE;
  397.     tmax[i] = -BOUND_HUGE;
  398.   }
  399.  
  400.   /* Get depths for all light sources and disconnected sampling intervals. */
  401.  
  402.   active = 0;
  403.  
  404.   intervals = 0;
  405.  
  406.   t1 = t2 = 0.0;
  407.  
  408.   Make_Colour(Max_Colour, 0.0, 0.0, 0.0);
  409.  
  410.   for (i = 0, Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source, i++)
  411.   {
  412.     insert = FALSE;
  413.  
  414.     Light_List[i].Light = Light;
  415.  
  416.     if (!Light->Atmosphere_Interaction)
  417.     {
  418.       continue;
  419.     }
  420.  
  421.     switch (Light->Light_Type)
  422.     {
  423.       case CYLINDER_SOURCE:
  424.  
  425.         if (intersect_cylinderlight(Ray, Light, &t1, &t2))
  426.         {
  427.           if ((t1 < Intersection->Depth) && (t2 > Small_Tolerance))
  428.           {
  429.             insert = TRUE;
  430.           }
  431.         }
  432.  
  433.         break;
  434.  
  435.       case POINT_SOURCE:
  436.  
  437.         t1 = 0.0;
  438.         t2 = Intersection->Depth;
  439.  
  440.         insert = TRUE;
  441.  
  442.         break;
  443.  
  444.       case SPOT_SOURCE:
  445.  
  446.         if (intersect_spotlight(Ray, Light, &t1, &t2))
  447.         {
  448.           if ((t1 < Intersection->Depth) && (t2 > Small_Tolerance))
  449.           {
  450.             insert = TRUE;
  451.           }
  452.         }
  453.  
  454.         break;
  455.     }
  456.  
  457.     /* Insert distances into sampling interval list. */
  458.  
  459.     if (insert)
  460.     {
  461.       /* Add light color to maximum color. */
  462.  
  463.       VAddEq(Max_Colour, Light->Colour);
  464.  
  465.       /* Number of active light sources. */
  466.  
  467.       active ++;
  468.  
  469.       /* Insert light source intersections into light list. */
  470.  
  471.       t1 = max(t1, 0.0);
  472.       t2 = min(t2, Intersection->Depth);
  473.  
  474.       Light_List[i].active = TRUE;
  475.       Light_List[i].t1 = t1;
  476.       Light_List[i].t2 = t2;
  477.  
  478.       /* Test if there's an overlapping interval. */
  479.  
  480.       for (j = 0; j < intervals; j++)
  481.       {
  482.         if (!((t2 < tmin[j]) || (t1 > tmax[j])))
  483.         {
  484.           /* The intervals are overlapping. */
  485.  
  486.           break;
  487.         }
  488.       }
  489.  
  490.       if (j >= intervals)
  491.       {
  492.         j = intervals;
  493.  
  494.         intervals++;
  495.       }
  496.  
  497.       /* Adjust interval. */
  498.  
  499.       tmin[j] = min(tmin[j], t1);
  500.       tmax[j] = max(tmax[j], t2);
  501.     }
  502.   }
  503.  
  504.   /* Initialize maximum color. */
  505.  
  506.   Max_Colour[RED]   = (Max_Colour[RED]   > EPSILON) ? 1.0 : 0.0;
  507.   Max_Colour[GREEN] = (Max_Colour[GREEN] > EPSILON) ? 1.0 : 0.0;
  508.   Max_Colour[BLUE]  = (Max_Colour[BLUE]  > EPSILON) ? 1.0 : 0.0;
  509.  
  510.   /*
  511.    * If there are no active lights, we can skip ahead because no
  512.    * light from any light source will reach the viewer.
  513.    */
  514.  
  515.   Make_Colour(Col_total, 0.0, 0.0, 0.0);
  516.  
  517.   if (active > 0)
  518.   {
  519.     for (interval = 0; interval < intervals; interval++)
  520.     {
  521.       /* Get sampling step distance. */
  522.  
  523.       step = min((tmax[interval] - tmin[interval]), Atmosphere->Distance) / (DBL)Atmosphere->Samples;
  524.  
  525.       /* Set up distance. */
  526.  
  527.       dist = dist_prev = 0.0;
  528.  
  529.       /* Sample along the ray. */
  530.  
  531.       Make_Colour(Col, 0.0, 0.0, 0.0);
  532.  
  533.       for (i = 0; dist < tmax[interval]; i++)
  534.       {
  535.         /* Step to next sample point. */
  536.  
  537.         dist = tmin[interval] + ((DBL)i + 0.5) * step;
  538.  
  539.         /* Get distance of current sampling point. */
  540.  
  541.         jdist = dist + Atmosphere->Jitter * step * (FRAND() - 0.5);
  542.  
  543.         /* If we're behind the intersection point we can quit. */
  544.  
  545.         if (jdist >= Intersection->Depth)
  546.         {
  547.           break;
  548.         }
  549.  
  550.         sample_atmosphere(Light_List, jdist, Ray, Atmosphere, Col);
  551.  
  552.         /* Add previous result to the total color. */
  553.  
  554.         if (i)
  555.         {
  556.           /* Do the current and previous colours differ too much? */
  557.  
  558.           if ((Atmosphere->AA_Level > 0) && (Colour_Distance(Col, Col_prev) >= Atmosphere->AA_Threshold))
  559.           {
  560.             /* Supersample between current and previous point. */
  561.  
  562.             supersample_atmosphere(Light_List, 1, Ray, Atmosphere, dist_prev, Col_prev, dist, Col);
  563.  
  564.             Col[RED]   = Col_prev[RED]   = 0.5 * (Col[RED]   + Col_prev[RED]);
  565.             Col[GREEN] = Col_prev[GREEN] = 0.5 * (Col[GREEN] + Col_prev[GREEN]);
  566.             Col[BLUE]  = Col_prev[BLUE]  = 0.5 * (Col[BLUE]  + Col_prev[BLUE]);
  567.           }
  568.  
  569.           /* Get attenuation due to distance from view point. */
  570.  
  571.           k = step * exp(-dist_prev / Atmosphere->Distance);
  572.  
  573.           /* If the contribution is too small we can stop. */
  574.  
  575.           if (k < BLACK_LEVEL)
  576.           {
  577.             break;
  578.           }
  579.  
  580.           Col_total[RED]   += k * Col_prev[RED];
  581.           Col_total[GREEN] += k * Col_prev[GREEN];
  582.           Col_total[BLUE]  += k * Col_prev[BLUE];
  583.  
  584.           /* If the total color is larger than max. value we can stop now. */
  585.  
  586.           if ((Col_total[RED]   >= Max_Colour[RED])   &&
  587.               (Col_total[GREEN] >= Max_Colour[GREEN]) &&
  588.               (Col_total[BLUE]  >= Max_Colour[BLUE]))
  589.           {
  590.             break;
  591.           }
  592.         }
  593.  
  594.         dist_prev = dist;
  595.  
  596.         Assign_Colour(Col_prev, Col);
  597.       }
  598.  
  599.       /* Add last result to the total color. */
  600.  
  601.       /* Get attenuation due to distance from view point. */
  602.  
  603.       k = step * exp(-dist / Atmosphere->Distance);
  604.  
  605.       Col_total[RED]   += k * Col_prev[RED];
  606.       Col_total[GREEN] += k * Col_prev[GREEN];
  607.       Col_total[BLUE]  += k * Col_prev[BLUE];
  608.  
  609.       /* If the total color is white already we can stop now. */
  610.  
  611.       if ((Col_total[RED] >= 1.0) && (Col_total[GREEN] >= 1.0) && (Col_total[BLUE] >= 1.0))
  612.       {
  613.         break;
  614.       }
  615.     }
  616.   }
  617.  
  618.   /* Add attenuated background color. */
  619.  
  620.   k = exp(-Intersection->Depth / Atmosphere->Distance);
  621.  
  622.   /* Check for minimum transmittance. */
  623.  
  624.   if (k < Atmosphere->Colour[TRANSM])
  625.   {
  626.     k = Atmosphere->Colour[TRANSM];
  627.   }
  628.  
  629. /*
  630.   ki = 1.0 - k;
  631.  
  632.   VLinComb3(Colour, 1.0, Col_total, k, Colour, ki, Atmosphere->Colour);
  633. */
  634.  
  635.   /* Attenuate color due to atmosphere color. */
  636.  
  637.   f = Atmosphere->Colour[FILTER];
  638.  
  639.   fi = 1.0 - f;
  640.  
  641.   C1[RED]   = Col_total[RED]   * (fi + f * Atmosphere->Colour[RED]);
  642.   C1[GREEN] = Col_total[GREEN] * (fi + f * Atmosphere->Colour[GREEN]);
  643.   C1[BLUE]  = Col_total[BLUE]  * (fi + f * Atmosphere->Colour[BLUE]);
  644.  
  645.   C2[RED]   = Colour[RED]   * (fi + f * Atmosphere->Colour[RED]);
  646.   C2[GREEN] = Colour[GREEN] * (fi + f * Atmosphere->Colour[GREEN]);
  647.   C2[BLUE]  = Colour[BLUE]  * (fi + f * Atmosphere->Colour[BLUE]);
  648.  
  649.   VLinComb2(Colour, 1.0, C1, k, C2);
  650.  
  651.   Colour[FILTER] = k * Colour[FILTER];
  652.   Colour[TRANSM] = k * Colour[TRANSM];
  653. }
  654.  
  655.  
  656.  
  657. /*****************************************************************************
  658. *
  659. * FUNCTION
  660. *
  661. *   supersample_atmosphere
  662. *
  663. * INPUT
  664. *
  665. *   Light_List   - array containing light source information
  666. *   level        - level of recursion
  667. *   Ray          - pointer to ray
  668. *   Atmosphere   - pointer to atmosphere to use
  669. *   d1           - distance to lower sample
  670. *   d3           - distance to upper sample
  671. *
  672. * OUTPUT
  673. *
  674. *   C1           - Color of lower sample
  675. *   C3           - Color of upper sample
  676. *
  677. * RETURNS
  678. *
  679. * AUTHOR
  680. *
  681. *   Dieter Bayer
  682. *
  683. * DESCRIPTION
  684. *
  685. *   Recursevily supersample between two points on the ray.
  686. *
  687. * CHANGES
  688. *
  689. *   Nov 1994 : Creation.
  690. *
  691. ******************************************************************************/
  692.  
  693. static void supersample_atmosphere(Light_List, level, Ray, Atmosphere, d1, C1, d3, C3)
  694. LIGHT_LIST *Light_List;
  695. int level;
  696. RAY *Ray;
  697. ATMOSPHERE *Atmosphere;
  698. DBL d1, d3;
  699. COLOUR C1, C3;
  700. {
  701.   DBL d2, jdist;
  702.   COLOUR C2;
  703.  
  704.   Increase_Counter(stats[Atmosphere_Supersamples]);
  705.  
  706.   /* Sample between lower and upper point. */
  707.  
  708.   d2 = 0.5 * (d1 + d3);
  709.  
  710.   jdist = d2 + Atmosphere->Jitter * 0.5 * (d3 - d1) * (FRAND() - 0.5);
  711.  
  712.   sample_atmosphere(Light_List, jdist, Ray, Atmosphere, C2);
  713.  
  714.   /* Test for further supersampling. */
  715.  
  716.   if (level < Atmosphere->AA_Level)
  717.   {
  718.     if (Colour_Distance(C1, C2) >= Atmosphere->AA_Threshold)
  719.     {
  720.       /* Supersample between lower and middle point. */
  721.  
  722.       supersample_atmosphere(Light_List, level+1, Ray, Atmosphere, d1, C1, d2, C2);
  723.     }
  724.  
  725.     if (Colour_Distance(C2, C3) >= Atmosphere->AA_Threshold)
  726.     {
  727.       /* Supersample between current and higher point. */
  728.  
  729.       supersample_atmosphere(Light_List, level+1, Ray, Atmosphere, d2, C2, d3, C3);
  730.     }
  731.   }
  732.  
  733.   /* Add supersampled colors. */
  734.  
  735.   VLinComb2(C1, 0.75, C1, 0.25, C2);
  736.   VLinComb2(C3, 0.25, C2, 0.75, C3);
  737. }
  738.  
  739.  
  740.  
  741. /*****************************************************************************
  742. *
  743. * FUNCTION
  744. *
  745. *   sample_atmosphere
  746. *
  747. * INPUT
  748. *
  749. *   Light_List   - array containing light source information
  750. *   dist         - distance of current sample
  751. *   Ray          - pointer to ray
  752. *   Atmosphere   - pointer to atmosphere to use
  753. *
  754. * OUTPUT
  755. *
  756. *   Col          - color of current sample
  757. *
  758. * RETURNS
  759. *
  760. * AUTHOR
  761. *
  762. *   Dieter Bayer
  763. *
  764. * DESCRIPTION
  765. *
  766. *   Calculate the color of the current atmosphere sample, i.e. the
  767. *   sample at distance dist, by summing the light reaching that point
  768. *   from all light sources.
  769. *
  770. * CHANGES
  771. *
  772. *   Nov 1994 : Creation.
  773. *
  774. ******************************************************************************/
  775.  
  776. static void sample_atmosphere(Light_List, dist, Ray, Atmosphere, Col)
  777. LIGHT_LIST *Light_List;
  778. DBL dist;
  779. RAY *Ray;
  780. ATMOSPHERE *Atmosphere;
  781. COLOUR Col;
  782. {
  783.   int i;
  784.   DBL alpha, len, k, g, g2;
  785.   VECTOR P;
  786.   COLOUR Light_Colour;
  787.   RAY Light_Ray;
  788.  
  789.   Increase_Counter(stats[Atmosphere_Samples]);
  790.  
  791.   /* Get current sample point. */
  792.  
  793.   VEvaluateRay(P, Ray->Initial, dist, Ray->Direction);
  794.  
  795.   /* Process all light sources. */
  796.  
  797.   Make_Colour(Col, 0.0, 0.0, 0.0);
  798.  
  799.   for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  800.   {
  801.     /* Use light only if active and within it's boundaries. */
  802.  
  803.     if (Light_List[i].active && (dist >= Light_List[i].t1) && (dist <= Light_List[i].t2))
  804.     {
  805.       if (!(Test_Shadow(Light_List[i].Light, &len, &Light_Ray, Ray, P, Light_Colour)))
  806.       {
  807.         VDot(alpha, Light_Ray.Direction, Ray->Direction);
  808.  
  809.         /* Get attenuation due to scattering. */
  810.  
  811.         switch (Atmosphere->Type)
  812.         {
  813.           case RAYLEIGH_SCATTERING:
  814.  
  815.             k = (1.0 + Sqr(alpha)) / 2.0;
  816.  
  817.             break;
  818.  
  819.           case MIE_HAZY_SCATTERING:
  820.  
  821.             k = 0.1 * (1.0 + 0.03515625 * pow(1.0 + alpha, 8.0));
  822.  
  823.             break;
  824.  
  825.           case MIE_MURKY_SCATTERING:
  826.  
  827.             k = 0.019607843 * (1.0 + 1.1641532e-8 * pow(1.0 + alpha, 32.0));
  828.  
  829.             break;
  830.  
  831.           case HENYEY_GREENSTEIN_SCATTERING:
  832.  
  833.             g = Atmosphere->Eccentricity;
  834.  
  835.             g2 = Sqr(g);
  836.  
  837.             k = (1.0 - g2) / pow(1.0 + g2 - 2.0 * g * alpha, 1.5);
  838.  
  839.             break;
  840.  
  841.           case ISOTROPIC_SCATTERING:
  842.           default:
  843.  
  844.             k = 1.0;
  845.  
  846.             break;
  847.         }
  848.  
  849.         k *= Atmosphere->Scattering;
  850.  
  851.         VAddScaledEq(Col, k, Light_Colour);
  852.       }
  853.     }
  854.   }
  855. }
  856.  
  857.  
  858.  
  859. /*****************************************************************************
  860. *
  861. * FUNCTION
  862. *
  863. *   do_fog
  864. *
  865. * INPUT
  866. *
  867. *   Ray            - current ray
  868. *   Intersection   - current intersection
  869. *   Light_Ray_Flag - TRUE if ray is a light source ray
  870. *
  871. * OUTPUT
  872. *
  873. *   Colour         - color of current ray
  874. *
  875. * RETURNS
  876. *
  877. * AUTHOR
  878. *
  879. *   POV-Ray Team
  880. *
  881. * DESCRIPTION
  882. *
  883. *   Evaluate all fogs for the current ray and intersection.
  884. *
  885. * CHANGES
  886. *
  887. *   Dec 1994 : Rewritten to allow multiple fogs. [DB]
  888. *
  889. *   Apr 1995 : Added transmittance threshold and filtering. [DB]
  890. *
  891. *   Jun 1995 : Added code for alpha channel support. [DB]
  892. *
  893. ******************************************************************************/
  894.  
  895. static void do_fog(Ray, Intersection, Colour, Light_Ray_Flag)
  896. RAY *Ray;
  897. INTERSECTION *Intersection;
  898. COLOUR Colour;
  899. int Light_Ray_Flag;
  900. {
  901.   DBL att, att_inv, width;
  902.   COLOUR Col_Fog;
  903.   COLOUR sum_att;  /* total attenuation. */
  904.   COLOUR sum_col;  /* total color.       */
  905.   FOG *Fog;
  906.  
  907.   /* Why are we here. */
  908.  
  909.   if (Frame.Fog == NULL)
  910.   {
  911.     return;
  912.   }
  913.  
  914.   /* Init total attenuation and total color. */
  915.  
  916.   Make_ColourA(sum_att, 1.0, 1.0, 1.0, 1.0, 1.0);
  917.   Make_ColourA(sum_col, 0.0, 0.0, 0.0, 0.0, 0.0);
  918.  
  919.   /* Loop over all fogs. */
  920.  
  921.   for (Fog = Frame.Fog; Fog != NULL; Fog = Fog->Next)
  922.   {
  923.     /* Don't care about fogs with zero distance. */
  924.  
  925.     if (fabs(Fog->Distance) > EPSILON)
  926.     {
  927.       width = Intersection->Depth;
  928.  
  929.       switch (Fog->Type)
  930.       {
  931.         case GROUND_MIST:
  932.  
  933.           att = ground_fog(Ray, 0.0, width, Fog, Col_Fog);
  934.  
  935.           break;
  936.  
  937.         default:
  938.  
  939.           att = constant_fog(Ray, 0.0, width, Fog, Col_Fog);
  940.  
  941.           break;
  942.       }
  943.  
  944.       /* Check for minimum transmittance. */
  945.  
  946.       if (att < Col_Fog[TRANSM])
  947.       {
  948.         att = Col_Fog[TRANSM];
  949.       }
  950.  
  951.       /* Get attenuation sum due to filtered/unfiltered translucency. */
  952.  
  953.       sum_att[RED]    *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[RED]);
  954.       sum_att[GREEN]  *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[GREEN]);
  955.       sum_att[BLUE]   *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[BLUE]);
  956.       sum_att[FILTER] *= att * Col_Fog[FILTER];
  957.       sum_att[TRANSM] *= att * Col_Fog[TRANSM];
  958.  
  959.       if (!Light_Ray_Flag)
  960.       {
  961.         att_inv = 1.0 - att;
  962.  
  963.         VAddScaledEq(sum_col, att_inv, Col_Fog);
  964.       }
  965.     }
  966.   }
  967.  
  968.   /* Add light coming from background. */
  969.  
  970.   sum_col[RED]    += sum_att[RED]    * Colour[RED];
  971.   sum_col[GREEN]  += sum_att[GREEN]  * Colour[GREEN];
  972.   sum_col[BLUE]   += sum_att[BLUE]   * Colour[BLUE];
  973.   sum_col[FILTER] += sum_att[FILTER] * Colour[FILTER];
  974.   sum_col[TRANSM] += sum_att[TRANSM] * Colour[TRANSM];
  975.  
  976.   Assign_Colour(Colour, sum_col);
  977. }
  978.  
  979.  
  980.  
  981. /*****************************************************************************
  982. *
  983. * FUNCTION
  984. *
  985. *   do_rainbow
  986. *
  987. * INPUT
  988. *
  989. *   Ray          - Current ray
  990. *   Intersection - Cuurent intersection
  991. *
  992. * OUTPUT
  993. *
  994. *   Colour       - Current colour
  995. *
  996. * RETURNS
  997. *
  998. * AUTHOR
  999. *
  1000. *   Dieter Bayer
  1001. *
  1002. * DESCRIPTION
  1003. *
  1004. *   Create a rainbow using an impressionistic model.
  1005. *
  1006. *   The model was taken from:
  1007. *
  1008. *     Musgrave, F. Kenton, "Prisms and Rainbows: a Dispersion Model
  1009. *     for Computer Graphics", Proceedings of Graphics Interface '89 -
  1010. *     Vision Interface '89, p. 227-234.
  1011. *
  1012. * CHANGES
  1013. *
  1014. *   Jul 1994 : Creation.
  1015. *
  1016. *   Dec 1994 : Modified to allow multiple rainbows. [DB]
  1017. *
  1018. *   Apr 1995 : Added rainbow arcs and filtering. [DB]
  1019. *
  1020. *   Jun 1995 : Added code for alpha channel support. [DB]
  1021. *
  1022. ******************************************************************************/
  1023.  
  1024. static void do_rainbow(Ray, Intersection, Colour)
  1025. RAY *Ray;
  1026. INTERSECTION *Intersection;
  1027. COLOUR Colour;
  1028. {
  1029.   int n;
  1030.   DBL dot, k, ki, index, x, y, l, angle, fade, f;
  1031.   VECTOR Temp;
  1032.   COLOUR Cr, Ct;
  1033.   RAINBOW *Rainbow;
  1034.  
  1035.   /* Why are we here. */
  1036.  
  1037.   if (Frame.Rainbow == NULL)
  1038.   {
  1039.     return;
  1040.   }
  1041.  
  1042.   Make_ColourA(Ct, 0.0, 0.0, 0.0, 1.0, 1.0);
  1043.  
  1044.   n = 0;
  1045.  
  1046.   for (Rainbow = Frame.Rainbow; Rainbow != NULL; Rainbow = Rainbow->Next)
  1047.   {
  1048.     if ((Rainbow->Pigment != NULL) && (Rainbow->Distance != 0.0) && (Rainbow->Width != 0.0))
  1049.     {
  1050.       /* Get angle between ray direction and rainbow's up vector. */
  1051.  
  1052.       VDot(x, Ray->Direction, Rainbow->Right_Vector);
  1053.       VDot(y, Ray->Direction, Rainbow->Up_Vector);
  1054.  
  1055.       l = Sqr(x) + Sqr(y);
  1056.  
  1057.       if (l > 0.0)
  1058.       {
  1059.         l = sqrt(l);
  1060.  
  1061.         y /= l;
  1062.       }
  1063.  
  1064.       angle = fabs(acos(y));
  1065.  
  1066.       if (angle <= Rainbow->Arc_Angle)
  1067.       {
  1068.         /* Get dot product between ray direction and antisolar vector. */
  1069.  
  1070.         VDot(dot, Ray->Direction, Rainbow->Antisolar_Vector);
  1071.  
  1072.         if (dot >= 0.0)
  1073.         {
  1074.           /* Get index ([0;1]) into rainbow's colour map. */
  1075.  
  1076.           index = (acos(dot) - Rainbow->Angle) / Rainbow->Width;
  1077.  
  1078.           /* Jitter index. */
  1079.  
  1080.           if (Rainbow->Jitter > 0.0)
  1081.           {
  1082.             index += (2.0 * FRAND() - 1.0) * Rainbow->Jitter;
  1083.           }
  1084.  
  1085.           if ((index >= 0.0) && (index <= 1.0 - EPSILON))
  1086.           {
  1087.             /* Get colour from rainbow's colour map. */
  1088.  
  1089.             Make_Vector(Temp, index, 0.0, 0.0);
  1090.  
  1091.             Compute_Pigment(Cr, Rainbow->Pigment, Temp);
  1092.  
  1093.             /* Get fading value for falloff. */
  1094.  
  1095.             if ((Rainbow->Falloff_Width > 0.0) && (angle > Rainbow->Falloff_Angle))
  1096.             {
  1097.               fade = (angle - Rainbow->Falloff_Angle) / Rainbow->Falloff_Width;
  1098.  
  1099.               fade = (3.0 - 2.0 * fade) * fade * fade;
  1100.             }
  1101.             else
  1102.             {
  1103.               fade = 0.0;
  1104.             }
  1105.  
  1106.             /* Get attenuation factor due to distance. */
  1107.  
  1108.             k = exp(-Intersection->Depth / Rainbow->Distance);
  1109.  
  1110.             /* Colour's transm value is used as minimum attenuation value. */
  1111.  
  1112.             k = max(k, fade * (1.0 - Cr[TRANSM]) + Cr[TRANSM]);
  1113.  
  1114.             /* Now interpolate the colours. */
  1115.  
  1116.             ki = 1.0 - k;
  1117.  
  1118.             /* Attenuate filter value. */
  1119.  
  1120.             f = Cr[FILTER] * ki;
  1121.  
  1122.             Ct[RED]    += k * Colour[RED]   * ((1.0 - f) + f * Cr[RED])   + ki * Cr[RED];
  1123.             Ct[GREEN]  += k * Colour[GREEN] * ((1.0 - f) + f * Cr[GREEN]) + ki * Cr[GREEN];
  1124.             Ct[BLUE]   += k * Colour[BLUE]  * ((1.0 - f) + f * Cr[BLUE])  + ki * Cr[BLUE];
  1125.             Ct[FILTER] *= k * Cr[FILTER];
  1126.             Ct[TRANSM] *= k * Cr[TRANSM];
  1127.  
  1128.             n++;
  1129.           }
  1130.         }
  1131.       }
  1132.     }
  1133.   }
  1134.  
  1135.   if (n > 0)
  1136.   {
  1137.     VInverseScale(Colour, Ct, (DBL)n);
  1138.  
  1139.     Colour[FILTER] *= Ct[FILTER];
  1140.     Colour[TRANSM] *= Ct[TRANSM];
  1141.   }
  1142. }
  1143.  
  1144.  
  1145.  
  1146. /*****************************************************************************
  1147. *
  1148. * FUNCTION
  1149. *
  1150. *   do_skysphere
  1151. *
  1152. * INPUT
  1153. *
  1154. *   Ray    - Current ray
  1155. *
  1156. * OUTPUT
  1157. *
  1158. *   Colour - Current color
  1159. *
  1160. * RETURNS
  1161. *
  1162. * AUTHOR
  1163. *
  1164. *   Dieter Bayer
  1165. *
  1166. * DESCRIPTION
  1167. *
  1168. *   Calculate color of the sky.
  1169. *
  1170. *   Use the ray direction as a point on the skysphere. Thus the sky can
  1171. *   easily be colored with all kinds of pigments.
  1172. *
  1173. * CHANGES
  1174. *
  1175. *   Jul 1994 : Creation.
  1176. *
  1177. *   Dec 1994 : Modified to allow layered pigments. [DB]
  1178. *
  1179. *   Jun 1995 : Added code for alpha channel support. [DB]
  1180. *
  1181. ******************************************************************************/
  1182.  
  1183. static void do_skysphere(Ray, Colour)
  1184. RAY *Ray;
  1185. COLOUR Colour;
  1186. {
  1187.   int i;
  1188.   DBL att, trans;
  1189.   COLOUR Col, Col_Temp, Filter;
  1190.   VECTOR P;
  1191.   SKYSPHERE *Skysphere;
  1192.  
  1193.   /* Why are we here. */
  1194.  
  1195.   if (Frame.Skysphere == NULL)
  1196.   {
  1197.     return;
  1198.   }
  1199.  
  1200.   Make_ColourA(Col, 0.0, 0.0, 0.0, 0.0, 0.0);
  1201.  
  1202.   if (((Skysphere = Frame.Skysphere) != NULL) && (Skysphere->Pigments != NULL))
  1203.   {
  1204.     Make_ColourA(Filter, 1.0, 1.0, 1.0, 1.0, 1.0);
  1205.  
  1206.     trans = 1.0;
  1207.  
  1208.     /* Transform point on unit sphere. */
  1209.  
  1210.     if (Skysphere->Trans != NULL)
  1211.     {
  1212.       MInvTransPoint(P, Ray->Direction, Skysphere->Trans);
  1213.     }
  1214.     else
  1215.     {
  1216.       Assign_Vector(P, Ray->Direction);
  1217.     }
  1218.  
  1219.     for (i = Skysphere->Count-1; i >= 0; i--)
  1220.     {
  1221.       /* Compute sky colour from colour map. */
  1222.  
  1223.       Compute_Pigment(Col_Temp, Skysphere->Pigments[i], P);
  1224.  
  1225.       att = trans * (1.0 - Col_Temp[FILTER] - Col_Temp[TRANSM]);
  1226.  
  1227.       VAddScaledEq(Col, att, Col_Temp);
  1228.  
  1229.       Filter[RED]    *= Col_Temp[RED];
  1230.       Filter[GREEN]  *= Col_Temp[GREEN];
  1231.       Filter[BLUE]   *= Col_Temp[BLUE];
  1232.       Filter[FILTER] *= Col_Temp[FILTER];
  1233.       Filter[TRANSM] *= Col_Temp[TRANSM];
  1234.  
  1235.       trans = fabs(Filter[FILTER]) + fabs(Filter[TRANSM]);
  1236.     }
  1237.  
  1238.     Colour[RED]    = Col[RED]    + Colour[RED]   * (Filter[RED]   * Filter[FILTER] + Filter[TRANSM]);
  1239.     Colour[GREEN]  = Col[GREEN]  + Colour[GREEN] * (Filter[GREEN] * Filter[FILTER] + Filter[TRANSM]);
  1240.     Colour[BLUE]   = Col[BLUE]   + Colour[BLUE]  * (Filter[BLUE]  * Filter[FILTER] + Filter[TRANSM]);
  1241.     Colour[FILTER] = Colour[FILTER] * Filter[FILTER];
  1242.     Colour[TRANSM] = Colour[TRANSM] * Filter[TRANSM];
  1243.   }
  1244. }
  1245.  
  1246.  
  1247.  
  1248. /*****************************************************************************
  1249. *
  1250. * FUNCTION
  1251. *
  1252. *   constant_fog
  1253. *
  1254. * INPUT
  1255. *
  1256. *   Ray    - current ray
  1257. *   Depth  - intersection depth with fog's boundary
  1258. *   Width  - width of the fog along the ray
  1259. *   Fog    - current fog
  1260. *
  1261. * OUTPUT
  1262. *
  1263. *   Colour - color of the fog
  1264. *
  1265. * RETURNS
  1266. *
  1267. * AUTHOR
  1268. *
  1269. *   POV-Ray Team
  1270. *
  1271. * DESCRIPTION
  1272. *
  1273. *   Apply distance attenuated fog.
  1274. *
  1275. * CHANGES
  1276. *
  1277. *   Dec 1994 : Modified to work with multiple fogs. [DB]
  1278. *
  1279. ******************************************************************************/
  1280.  
  1281. static DBL constant_fog(Ray, Depth, Width, Fog, Colour)
  1282. RAY *Ray;
  1283. DBL Depth, Width;
  1284. FOG *Fog;
  1285. COLOUR Colour;
  1286. {
  1287.   DBL k;
  1288.   VECTOR P;
  1289.  
  1290.   if (Fog->Turb != NULL)
  1291.   {
  1292.     Depth += Width / 2.0;
  1293.  
  1294.     VEvaluateRay(P, Ray->Initial, Depth, Ray->Direction);
  1295.  
  1296.     VEvaluateEq(P, Fog->Turb->Turbulence);
  1297.  
  1298.     /* The further away the less influence turbulence has. */
  1299.  
  1300.     k = exp(-Width / Fog->Distance);
  1301.  
  1302.     Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb)*Fog->Turb_Depth);
  1303.   }
  1304.  
  1305.   Assign_Colour(Colour, Fog->Colour);
  1306.  
  1307.   return (exp(-Width / Fog->Distance));
  1308. }
  1309.  
  1310.  
  1311.  
  1312. /*****************************************************************************
  1313. *
  1314. * FUNCTION
  1315. *
  1316. *   ground_fog
  1317. *
  1318. * INPUT
  1319. *
  1320. *   Ray   - current ray
  1321. *   Depth - intersection depth with fog's boundary
  1322. *   Width - width of the fog along the ray
  1323. *   Fog   - current fog
  1324. *
  1325. * OUTPUT
  1326. *
  1327. *   Colour - color of the fog
  1328. *
  1329. * RETURNS
  1330. *
  1331. * AUTHOR
  1332. *
  1333. *   Eric Barish
  1334. *
  1335. * DESCRIPTION
  1336. *
  1337. *   Here is an ascii graph of the ground fog density, it has a maximum
  1338. *   density of 1.0 at Y <= 0, and approaches 0.0 as Y goes up:
  1339. *
  1340. *   ***********************************
  1341. *        |           |            |    ****
  1342. *        |           |            |        ***
  1343. *        |           |            |           ***
  1344. *        |           |            |            | ****
  1345. *        |           |            |            |     *****
  1346. *        |           |            |            |          *******
  1347. *   -----+-----------+------------+------------+-----------+-----
  1348. *       Y=-2        Y=-1         Y=0          Y=1         Y=2
  1349. *
  1350. *   ground fog density is 1 / (Y*Y+1) for Y >= 0 and equals 1.0 for Y <= 0.
  1351. *   (It behaves like regular fog for Y <= 0.)
  1352. *
  1353. *   The integral of the density is atan(Y) (for Y >= 0).
  1354. *
  1355. * CHANGES
  1356. *
  1357. *   Feb 1996 : Changed to behave like normal fog for Y <= 0.
  1358. *              Fixed bug with reversed offset effect. [DB]
  1359. *
  1360. ******************************************************************************/
  1361.  
  1362. static DBL ground_fog(Ray, Depth, Width, Fog, Colour)
  1363. RAY *Ray;
  1364. DBL Depth, Width;
  1365. FOG *Fog;
  1366. COLOUR Colour;
  1367. {
  1368.   DBL fog_density, delta;
  1369.   DBL start, end;
  1370.   DBL y1, y2, k;
  1371.   VECTOR P, P1, P2;
  1372.  
  1373.   /* Get start point. */
  1374.  
  1375.   VEvaluateRay(P1, Ray->Initial, Depth, Ray->Direction);
  1376.  
  1377.   /* Get end point. */
  1378.  
  1379.   VLinComb2(P2, 1.0, P1, Width, Ray->Direction);
  1380.  
  1381.   /*
  1382.    * Could preform transfomation here to translate Start and End
  1383.    * points into ground fog space.
  1384.    */
  1385.  
  1386.   VDot(y1, P1, Fog->Up);
  1387.   VDot(y2, P2, Fog->Up);
  1388.  
  1389.   start = (y1 - Fog->Offset) / Fog->Alt;
  1390.   end   = (y2 - Fog->Offset) / Fog->Alt;
  1391.  
  1392.   /* Get integral along y-axis from start to end. */
  1393.  
  1394.   if (start <= 0.0)
  1395.   {
  1396.     if (end <= 0.0)
  1397.     {
  1398.       fog_density = 1.0;
  1399.     }
  1400.     else
  1401.     {
  1402.       fog_density = (atan(end) - start) / (end - start);
  1403.     }
  1404.   }
  1405.   else
  1406.   {
  1407.     if (end <= 0.0)
  1408.     {
  1409.       fog_density = (atan(start) - end) / (start - end);
  1410.     }
  1411.     else
  1412.     {
  1413.       delta = start - end;
  1414.  
  1415.       if (fabs(delta) > EPSILON)
  1416.       {
  1417.         fog_density = (atan(start) - atan(end)) / delta;
  1418.       }
  1419.       else
  1420.       {
  1421.         fog_density = 1.0 / (Sqr(start) + 1.0);
  1422.       }
  1423.     }
  1424.   }
  1425.  
  1426.   /* Apply turbulence. */
  1427.  
  1428.   if (Fog->Turb != NULL)
  1429.   {
  1430.     VHalf(P, P1, P2);
  1431.  
  1432.     VEvaluateEq(P, Fog->Turb->Turbulence);
  1433.  
  1434.     /* The further away the less influence turbulence has. */
  1435.  
  1436.     k = exp(-Width / Fog->Distance);
  1437.  
  1438.     Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb)*Fog->Turb_Depth);
  1439.   }
  1440.  
  1441.   Assign_Colour(Colour, Fog->Colour);
  1442.  
  1443.   return (exp(-Width * fog_density / Fog->Distance));
  1444. }
  1445.  
  1446.  
  1447.  
  1448. /*****************************************************************************
  1449. *
  1450. * FUNCTION
  1451. *
  1452. *   intersect_spotlight
  1453. *
  1454. * INPUT
  1455. *
  1456. *   Ray    - current ray
  1457. *   Light  - current light source
  1458. *
  1459. * OUTPUT
  1460. *
  1461. *   d1, d2 - intersection depths
  1462. *
  1463. * RETURNS
  1464. *
  1465. *   int - TRUE, if hit
  1466. *
  1467. * AUTHOR
  1468. *
  1469. *   Dieter Bayer
  1470. *
  1471. * DESCRIPTION
  1472. *
  1473. *   Intersect a ray with the light cone of a spotlight.
  1474. *
  1475. * CHANGES
  1476. *
  1477. *   Nov 1994 : Creation.
  1478. *
  1479. ******************************************************************************/
  1480.  
  1481. static int intersect_spotlight(Ray, Light, d1, d2)
  1482. RAY *Ray;
  1483. LIGHT_SOURCE *Light;
  1484. DBL *d1, *d2;
  1485. {
  1486.   int viewpoint_is_in_cone;
  1487.   DBL a, b, c, d, m, l, l1, l2, t, t1, t2, k1, k2, k3, k4;
  1488.   VECTOR V1;
  1489.  
  1490.   /* Get cone's slope. Note that cos(falloff) is stored in Falloff! */
  1491.  
  1492.   a = acos(Light->Falloff);
  1493.  
  1494.   /* This only works for a < 180 degrees! */
  1495.  
  1496.   m = tan(a);
  1497.  
  1498.   m = 1.0 + Sqr(m);
  1499.  
  1500.   VSub(V1, Ray->Initial, Light->Center);
  1501.  
  1502.   VDot(k1, Ray->Direction, Light->Direction);
  1503.  
  1504.   VDot(k2, V1, Light->Direction);
  1505.  
  1506.   VLength(l, V1);
  1507.  
  1508.   if (l > EPSILON)
  1509.   {
  1510.     viewpoint_is_in_cone = (k2 / l >= Light->Falloff);
  1511.   }
  1512.   else
  1513.   {
  1514.     viewpoint_is_in_cone = FALSE;
  1515.   }
  1516.  
  1517.   if ((k1 <= 0.0) && (k2 < 0.0))
  1518.   {
  1519.     return (FALSE);
  1520.   }
  1521.  
  1522.   VDot(k3, V1, Ray->Direction);
  1523.  
  1524.   VDot(k4, V1, V1);
  1525.  
  1526.   a = 1.0 - Sqr(k1) * m;
  1527.  
  1528.   b = k3 - k1 * k2 * m;
  1529.  
  1530.   c = k4 - Sqr(k2) * m;
  1531.  
  1532.   if (a != 0.0)
  1533.   {
  1534.     d = Sqr(b) - a * c;
  1535.  
  1536.     if (d > EPSILON)
  1537.     {
  1538.       d = sqrt(d);
  1539.  
  1540.       t1 = (-b + d) / a;
  1541.       t2 = (-b - d) / a;
  1542.  
  1543.       if (t1 > t2)
  1544.       {
  1545.         t = t1; t1 = t2; t2 = t;
  1546.       }
  1547.  
  1548.       l1 = k2 + t1 * k1;
  1549.       l2 = k2 + t2 * k1;
  1550.  
  1551.       if ((l1 <= 0.0) && (l2 <= 0.0))
  1552.       {
  1553.         return (FALSE);
  1554.       }
  1555.  
  1556.       if ((l1 <= 0.0) || (l2 <= 0.0))
  1557.       {
  1558.         if (l1 <= 0.0)
  1559.         {
  1560.           if (viewpoint_is_in_cone)
  1561.           {
  1562.             t1 = 0.0;
  1563.             t2 = (t2 > 0.0) ? (t2) : (Max_Distance);
  1564.           }
  1565.           else
  1566.           {
  1567.             t1 = t2;
  1568.             t2 = Max_Distance;
  1569.           }
  1570.         }
  1571.         else
  1572.         {
  1573.           if (viewpoint_is_in_cone)
  1574.           {
  1575.             t2 = t1;
  1576.             t1 = 0.0;
  1577.           }
  1578.           else
  1579.           {
  1580.             t2 = Max_Distance;
  1581.           }
  1582.         }
  1583.       }
  1584.  
  1585.       *d1 = t1;
  1586.       *d2 = t2;
  1587.  
  1588.       return (TRUE);
  1589.     }
  1590.     else
  1591.     {
  1592.       if (d > -EPSILON)
  1593.       {
  1594.         if (viewpoint_is_in_cone)
  1595.         {
  1596.           *d1 = 0.0;
  1597.           *d2 = -b / a;
  1598.         }
  1599.         else
  1600.         {
  1601.           *d1 = -b / a;
  1602.           *d2 = Max_Distance;
  1603.         }
  1604.  
  1605.         return(TRUE);
  1606.       }
  1607.     }
  1608.   }
  1609.   else
  1610.   {
  1611.     if (viewpoint_is_in_cone)
  1612.     {
  1613.       *d1 = 0.0;
  1614.       *d2 = -c/b;
  1615.  
  1616.       return(TRUE);
  1617.     }
  1618.   }
  1619.  
  1620.   return (FALSE);
  1621. }
  1622.  
  1623.  
  1624.  
  1625. /*****************************************************************************
  1626. *
  1627. * FUNCTION
  1628. *
  1629. *   intersect_cylinderlight
  1630. *
  1631. * INPUT
  1632. *
  1633. *   Ray    - current ray
  1634. *   Light  - current light source
  1635. *
  1636. * OUTPUT
  1637. *
  1638. *   d1, d2 - intersection depths
  1639. *
  1640. * RETURNS
  1641. *
  1642. *   int - TRUE, if hit
  1643. *
  1644. * AUTHOR
  1645. *
  1646. *   Dieter Bayer
  1647. *
  1648. * DESCRIPTION
  1649. *
  1650. *   Intersect a ray with the light cylinder of a cylinderlight.
  1651. *
  1652. * CHANGES
  1653. *
  1654. *   Jan 1995 : Creation.
  1655. *
  1656. ******************************************************************************/
  1657.  
  1658. static int intersect_cylinderlight(Ray, Light, d1, d2)
  1659. RAY *Ray;
  1660. LIGHT_SOURCE *Light;
  1661. DBL *d1, *d2;
  1662. {
  1663.   DBL a, b, c, d, l1, l2, t, t1, t2, k1, k2, k3, k4;
  1664.   VECTOR V1;
  1665.  
  1666.   VSub(V1, Ray->Initial, Light->Center);
  1667.  
  1668.   VDot(k1, Ray->Direction, Light->Direction);
  1669.  
  1670.   VDot(k2, V1, Light->Direction);
  1671.  
  1672.   if ((k1 <= 0.0) && (k2 < 0.0))
  1673.   {
  1674.     return (FALSE);
  1675.   }
  1676.  
  1677.   a = 1.0 - Sqr(k1);
  1678.  
  1679.   if (a != 0.0)
  1680.   {
  1681.     VDot(k3, V1, Ray->Direction);
  1682.  
  1683.     VDot(k4, V1, V1);
  1684.  
  1685.     b = k3 - k1 * k2;
  1686.  
  1687.     c = k4 - Sqr(k2) - Sqr(Light->Falloff);
  1688.  
  1689.     d = Sqr(b) - a * c;
  1690.  
  1691.     if (d > EPSILON)
  1692.     {
  1693.       d = sqrt(d);
  1694.  
  1695.       t1 = (-b + d) / a;
  1696.       t2 = (-b - d) / a;
  1697.  
  1698.       if (t1 > t2)
  1699.       {
  1700.         t = t1; t1 = t2; t2 = t;
  1701.       }
  1702.  
  1703.       l1 = k2 + t1 * k1;
  1704.       l2 = k2 + t2 * k1;
  1705.  
  1706.       if ((l1 <= 0.0) && (l2 <= 0.0))
  1707.       {
  1708.         return (FALSE);
  1709.       }
  1710.  
  1711.       if ((l1 <= 0.0) || (l2 <= 0.0))
  1712.       {
  1713.         if (l1 <= 0.0)
  1714.         {
  1715.           t1 = 0.0;
  1716.         }
  1717.         else
  1718.         {
  1719.           t2 = (Max_Distance - k2) / k1;
  1720.         }
  1721.       }
  1722.  
  1723.       *d1 = t1;
  1724.       *d2 = t2;
  1725.  
  1726.       return (TRUE);
  1727.     }
  1728.   }
  1729.  
  1730.   return (FALSE);
  1731. }
  1732.  
  1733.  
  1734.  
  1735. /*****************************************************************************
  1736. *
  1737. * FUNCTION
  1738. *
  1739. *   Create_Atmosphere
  1740. *
  1741. * INPUT
  1742. *
  1743. * OUTPUT
  1744. *
  1745. * RETURNS
  1746. *
  1747. *   ATMOSPHERE * - created atmosphere
  1748. *
  1749. * AUTHOR
  1750. *
  1751. *   Dieter Bayer
  1752. *
  1753. * DESCRIPTION
  1754. *
  1755. *   Create an atmosphere.
  1756. *
  1757. * CHANGES
  1758. *
  1759. *   Dec 1994 : Creation.
  1760. *
  1761. ******************************************************************************/
  1762.  
  1763. ATMOSPHERE *Create_Atmosphere()
  1764. {
  1765.   ATMOSPHERE *New;
  1766.  
  1767.   New = (ATMOSPHERE *)POV_MALLOC(sizeof(ATMOSPHERE), "fog");
  1768.  
  1769.   New->Type = ISOTROPIC_SCATTERING;
  1770.  
  1771.   New->Samples            = 100;
  1772.   New->Distance           = 0.0;
  1773.   New->Distance_Threshold = 0.005;
  1774.   New->Scattering         = 1.0;
  1775.   New->Eccentricity       = 0.0;
  1776.  
  1777.   Make_Colour(New->Colour, 0.0, 0.0, 0.0);
  1778.  
  1779.   New->AA_Level     = 0;
  1780.   New->AA_Threshold = 0.3;
  1781.   New->Jitter       = 0.0;
  1782.  
  1783.   return (New);
  1784. }
  1785.  
  1786.  
  1787.  
  1788. /*****************************************************************************
  1789. *
  1790. * FUNCTION
  1791. *
  1792. *   Copy_Atmosphere
  1793. *
  1794. * INPUT
  1795. *
  1796. *   Old - atmosphere to copy
  1797. *
  1798. * OUTPUT
  1799. *
  1800. * RETURNS
  1801. *
  1802. *   ATMOSPHERE * - new atmosphere
  1803. *
  1804. * AUTHOR
  1805. *
  1806. *   Dieter Bayer
  1807. *
  1808. * DESCRIPTION
  1809. *
  1810. *   Copy an atmosphere.
  1811. *
  1812. * CHANGES
  1813. *
  1814. *   Dec 1994 : Creation.
  1815. *
  1816. ******************************************************************************/
  1817.  
  1818. void *Copy_Atmosphere(Old)
  1819. ATMOSPHERE *Old;
  1820. {
  1821.   ATMOSPHERE *New;
  1822.  
  1823.   New = Create_Atmosphere();
  1824.  
  1825.   *New = *Old;
  1826.  
  1827.   return (New);
  1828. }
  1829.  
  1830.  
  1831.  
  1832. /*****************************************************************************
  1833. *
  1834. * FUNCTION
  1835. *
  1836. *   Destroy_Atmosphere
  1837. *
  1838. * INPUT
  1839. *
  1840. *   Atmosphere - atmosphere to destroy
  1841. *
  1842. * OUTPUT
  1843. *
  1844. * RETURNS
  1845. *
  1846. * AUTHOR
  1847. *
  1848. *   Dieter Bayer
  1849. *
  1850. * DESCRIPTION
  1851. *
  1852. *   Destroy an atmosphere.
  1853. *
  1854. * CHANGES
  1855. *
  1856. *   Dec 1994 : Creation.
  1857. *
  1858. ******************************************************************************/
  1859.  
  1860. void Destroy_Atmosphere(Atmosphere)
  1861. ATMOSPHERE *Atmosphere;
  1862. {
  1863.   if (Atmosphere != NULL)
  1864.   {
  1865.     POV_FREE(Atmosphere);
  1866.   }
  1867. }
  1868.  
  1869.  
  1870.  
  1871. /*****************************************************************************
  1872. *
  1873. * FUNCTION
  1874. *
  1875. *   Create_Fog
  1876. *
  1877. * INPUT
  1878. *
  1879. * OUTPUT
  1880. *
  1881. * RETURNS
  1882. *
  1883. *   FOG * - created fog
  1884. *
  1885. * AUTHOR
  1886. *
  1887. *   Dieter Bayer
  1888. *
  1889. * DESCRIPTION
  1890. *
  1891. *   Create a fog.
  1892. *
  1893. * CHANGES
  1894. *
  1895. *   Dec 1994 : Creation.
  1896. *
  1897. ******************************************************************************/
  1898.  
  1899. FOG *Create_Fog()
  1900. {
  1901.   FOG *New;
  1902.  
  1903.   New = (FOG *)POV_MALLOC(sizeof(FOG), "fog");
  1904.  
  1905.   New->Type = ORIG_FOG;
  1906.  
  1907.   New->Distance = 0.0;
  1908.   New->Alt      = 0.0;
  1909.   New->Offset   = 0.0;
  1910.  
  1911.   Make_ColourA(New->Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  1912.  
  1913.   Make_Vector(New->Up, 0.0, 1.0, 0.0);
  1914.  
  1915.   New->Turb = NULL;
  1916.   New->Turb_Depth = 0.5;
  1917.  
  1918.   New->Next = NULL;
  1919.  
  1920.   return (New);
  1921. }
  1922.  
  1923.  
  1924.  
  1925. /*****************************************************************************
  1926. *
  1927. * FUNCTION
  1928. *
  1929. *   Copy_Fog
  1930. *
  1931. * INPUT
  1932. *
  1933. *   Old - fog to copy
  1934. *
  1935. * OUTPUT
  1936. *
  1937. * RETURNS
  1938. *
  1939. *   FOG * - new fog
  1940. *
  1941. * AUTHOR
  1942. *
  1943. *   Dieter Bayer
  1944. *
  1945. * DESCRIPTION
  1946. *
  1947. *   Copy a fog.
  1948. *
  1949. * CHANGES
  1950. *
  1951. *   Dec 1994 : Creation.
  1952. *
  1953. ******************************************************************************/
  1954.  
  1955. void *Copy_Fog(Old)
  1956. FOG *Old;
  1957. {
  1958.   FOG *New;
  1959.  
  1960.   New = Create_Fog();
  1961.  
  1962.   *New = *Old;
  1963.  
  1964.   New->Turb = (TURB *)Copy_Warps(((WARP *)Old->Turb));
  1965.  
  1966.   return (New);
  1967. }
  1968.  
  1969.  
  1970.  
  1971. /*****************************************************************************
  1972. *
  1973. * FUNCTION
  1974. *
  1975. *   Destroy_Fog
  1976. *
  1977. * INPUT
  1978. *
  1979. *   Fog - fog to destroy
  1980. *
  1981. * OUTPUT
  1982. *
  1983. * RETURNS
  1984. *
  1985. * AUTHOR
  1986. *
  1987. *   Dieter Bayer
  1988. *
  1989. * DESCRIPTION
  1990. *
  1991. *   Destroy a fog.
  1992. *
  1993. * CHANGES
  1994. *
  1995. *   Dec 1994 : Creation.
  1996. *
  1997. ******************************************************************************/
  1998.  
  1999. void Destroy_Fog(Fog)
  2000. FOG *Fog;
  2001. {
  2002.   if (Fog != NULL)
  2003.   {
  2004.     Destroy_Turb(Fog->Turb);
  2005.  
  2006.     POV_FREE(Fog);
  2007.   }
  2008. }
  2009.  
  2010.  
  2011.  
  2012. /*****************************************************************************
  2013. *
  2014. * FUNCTION
  2015. *
  2016. *   Create_Rainbow
  2017. *
  2018. * INPUT
  2019. *
  2020. * OUTPUT
  2021. *
  2022. * RETURNS
  2023. *
  2024. *   RAINBOW * - created rainbow
  2025. *
  2026. * AUTHOR
  2027. *
  2028. *   Dieter Bayer
  2029. *
  2030. * DESCRIPTION
  2031. *
  2032. *   Create a rainbow.
  2033. *
  2034. * CHANGES
  2035. *
  2036. *   Dec 1994 : Creation.
  2037. *
  2038. ******************************************************************************/
  2039.  
  2040. RAINBOW *Create_Rainbow()
  2041. {
  2042.   RAINBOW *New;
  2043.  
  2044.   New = (RAINBOW *)POV_MALLOC(sizeof(RAINBOW), "fog");
  2045.  
  2046.   New->Distance = Max_Distance;
  2047.   New->Jitter   = 0.0;
  2048.   New->Angle    = 0.0;
  2049.   New->Width    = 0.0;
  2050.  
  2051.   New->Falloff_Width  = 0.0;
  2052.   New->Arc_Angle      = 180.0;
  2053.   New->Falloff_Angle  = 180.0;
  2054.  
  2055.   New->Pigment = NULL;
  2056.  
  2057.   Make_Vector(New->Antisolar_Vector, 0.0, 0.0, 0.0);
  2058.  
  2059.   Make_Vector(New->Right_Vector, 1.0, 0.0, 0.0);
  2060.   Make_Vector(New->Up_Vector, 0.0, 1.0, 0.0);
  2061.  
  2062.   New->Next = NULL;
  2063.  
  2064.   return (New);
  2065. }
  2066.  
  2067.  
  2068.  
  2069. /*****************************************************************************
  2070. *
  2071. * FUNCTION
  2072. *
  2073. *   Copy_Rainbow
  2074. *
  2075. * INPUT
  2076. *
  2077. *   Old - rainbow to copy
  2078. *
  2079. * OUTPUT
  2080. *
  2081. * RETURNS
  2082. *
  2083. *   RAINBOW * - new rainbow
  2084. *
  2085. * AUTHOR
  2086. *
  2087. *   Dieter Bayer
  2088. *
  2089. * DESCRIPTION
  2090. *
  2091. *   Copy a rainbow.
  2092. *
  2093. * CHANGES
  2094. *
  2095. *   Dec 1994 : Creation.
  2096. *
  2097. ******************************************************************************/
  2098.  
  2099. void *Copy_Rainbow(Old)
  2100. RAINBOW *Old;
  2101. {
  2102.   RAINBOW *New;
  2103.  
  2104.   New = Create_Rainbow();
  2105.  
  2106.   *New = *Old;
  2107.  
  2108.   return (New);
  2109. }
  2110.  
  2111.  
  2112.  
  2113. /*****************************************************************************
  2114. *
  2115. * FUNCTION
  2116. *
  2117. *   Destroy_Rainbow
  2118. *
  2119. * INPUT
  2120. *
  2121. *   Rainbow - rainbow to destroy
  2122. *
  2123. * OUTPUT
  2124. *
  2125. * RETURNS
  2126. *
  2127. * AUTHOR
  2128. *
  2129. *   Dieter Bayer
  2130. *
  2131. * DESCRIPTION
  2132. *
  2133. *   Destroy a rainbow.
  2134. *
  2135. * CHANGES
  2136. *
  2137. *   Dec 1994 : Creation.
  2138. *
  2139. ******************************************************************************/
  2140.  
  2141. void Destroy_Rainbow(Rainbow)
  2142. RAINBOW *Rainbow;
  2143. {
  2144.   if (Rainbow != NULL)
  2145.   {
  2146.     Destroy_Pigment(Rainbow->Pigment);
  2147.  
  2148.     POV_FREE(Rainbow);
  2149.   }
  2150. }
  2151.  
  2152.  
  2153.  
  2154. /*****************************************************************************
  2155. *
  2156. * FUNCTION
  2157. *
  2158. *   Create_Skysphere
  2159. *
  2160. * INPUT
  2161. *
  2162. * OUTPUT
  2163. *
  2164. * RETURNS
  2165. *
  2166. *   SKYSPHERE * - created skysphere
  2167. *
  2168. * AUTHOR
  2169. *
  2170. *   Dieter Bayer
  2171. *
  2172. * DESCRIPTION
  2173. *
  2174. *   Create a skysphere.
  2175. *
  2176. * CHANGES
  2177. *
  2178. *   Dec 1994 : Creation.
  2179. *
  2180. ******************************************************************************/
  2181.  
  2182. SKYSPHERE *Create_Skysphere()
  2183. {
  2184.   SKYSPHERE *New;
  2185.  
  2186.   New = (SKYSPHERE *)POV_MALLOC(sizeof(SKYSPHERE), "fog");
  2187.  
  2188.   New->Count = 0;
  2189.  
  2190.   New->Pigments = NULL;
  2191.  
  2192.   New->Trans = Create_Transform();
  2193.  
  2194.   return (New);
  2195. }
  2196.  
  2197.  
  2198.  
  2199. /*****************************************************************************
  2200. *
  2201. * FUNCTION
  2202. *
  2203. *   Copy_Skysphere
  2204. *
  2205. * INPUT
  2206. *
  2207. *   Old - skysphere to copy
  2208. *
  2209. * OUTPUT
  2210. *
  2211. * RETURNS
  2212. *
  2213. *   SKYSPHERE * - copied skysphere
  2214. *
  2215. * AUTHOR
  2216. *
  2217. *   Dieter Bayer
  2218. *
  2219. * DESCRIPTION
  2220. *
  2221. *   Copy a skysphere.
  2222. *
  2223. * CHANGES
  2224. *
  2225. *   Dec 1994 : Creation.
  2226. *
  2227. ******************************************************************************/
  2228.  
  2229. void *Copy_Skysphere(Old)
  2230. SKYSPHERE *Old;
  2231. {
  2232.   int i;
  2233.   SKYSPHERE *New;
  2234.  
  2235.   New = Create_Skysphere();
  2236.  
  2237.   Destroy_Transform(New->Trans);
  2238.  
  2239.   *New = *Old;
  2240.  
  2241.   New->Trans = Copy_Transform(Old->Trans);
  2242.  
  2243.   if (New->Count > 0)
  2244.   {
  2245.     New->Pigments = (PIGMENT **)POV_MALLOC(New->Count*sizeof(PIGMENT *), "skysphere pigment");
  2246.  
  2247.     for (i = 0; i < New->Count; i++)
  2248.     {
  2249.       New->Pigments[i] = Copy_Pigment(Old->Pigments[i]);
  2250.     }
  2251.   }
  2252.  
  2253.   return (New);
  2254. }
  2255.  
  2256.  
  2257.  
  2258. /*****************************************************************************
  2259. *
  2260. * FUNCTION
  2261. *
  2262. *   Destroy_Skysphere
  2263. *
  2264. * INPUT
  2265. *
  2266. *   Skysphere - skysphere to destroy
  2267. *
  2268. * OUTPUT
  2269. *
  2270. * RETURNS
  2271. *
  2272. * AUTHOR
  2273. *
  2274. *   Dieter Bayer
  2275. *
  2276. * DESCRIPTION
  2277. *
  2278. *   Destroy a skysphere.
  2279. *
  2280. * CHANGES
  2281. *
  2282. *   Dec 1994 : Creation.
  2283. *
  2284. ******************************************************************************/
  2285.  
  2286. void Destroy_Skysphere(Skysphere)
  2287. SKYSPHERE *Skysphere;
  2288. {
  2289.   int i;
  2290.  
  2291.   if (Skysphere != NULL)
  2292.   {
  2293.     for (i = 0; i < Skysphere->Count; i++)
  2294.     {
  2295.       Destroy_Pigment(Skysphere->Pigments[i]);
  2296.     }
  2297.  
  2298.     POV_FREE(Skysphere->Pigments);
  2299.  
  2300.     Destroy_Transform(Skysphere->Trans);
  2301.  
  2302.     POV_FREE(Skysphere);
  2303.   }
  2304. }
  2305.  
  2306.  
  2307.  
  2308. /*****************************************************************************
  2309. *
  2310. * FUNCTION
  2311. *
  2312. *   Rotate_Skysphere
  2313. *
  2314. * INPUT
  2315. *
  2316. *   Vector - Rotation vector
  2317. *
  2318. * OUTPUT
  2319. *
  2320. *   Skysphere - Pointer to skysphere structure
  2321. *
  2322. * RETURNS
  2323. *
  2324. * AUTHOR
  2325. *
  2326. *   Dieter Bayer
  2327. *
  2328. * DESCRIPTION
  2329. *
  2330. *   Rotate a skysphere.
  2331. *
  2332. * CHANGES
  2333. *
  2334. *   Feb 1996 : Creation.
  2335. *
  2336. ******************************************************************************/
  2337.  
  2338. void Rotate_Skysphere(Skysphere, Vector)
  2339. SKYSPHERE *Skysphere;
  2340. VECTOR Vector;
  2341. {
  2342.   TRANSFORM Trans;
  2343.  
  2344.   Compute_Rotation_Transform(&Trans, Vector);
  2345.  
  2346.   Transform_Skysphere(Skysphere, &Trans);
  2347. }
  2348.  
  2349.  
  2350.  
  2351. /*****************************************************************************
  2352. *
  2353. * FUNCTION
  2354. *
  2355. *   Scale_Skysphere
  2356. *
  2357. * INPUT
  2358. *
  2359. *   Vector - Scaling vector
  2360. *
  2361. * OUTPUT
  2362. *
  2363. *   Skysphere - Pointer to skysphere structure
  2364. *
  2365. * RETURNS
  2366. *
  2367. * AUTHOR
  2368. *
  2369. *   Dieter Bayer
  2370. *
  2371. * DESCRIPTION
  2372. *
  2373. *   Scale a skysphere.
  2374. *
  2375. * CHANGES
  2376. *
  2377. *   Feb 1996 : Creation.
  2378. *
  2379. ******************************************************************************/
  2380.  
  2381. void Scale_Skysphere(Skysphere, Vector)
  2382. SKYSPHERE *Skysphere;
  2383. VECTOR Vector;
  2384. {
  2385.   TRANSFORM Trans;
  2386.  
  2387.   Compute_Scaling_Transform(&Trans, Vector);
  2388.  
  2389.   Transform_Skysphere(Skysphere, &Trans);
  2390. }
  2391.  
  2392.  
  2393.  
  2394. /*****************************************************************************
  2395. *
  2396. * FUNCTION
  2397. *
  2398. *   Translate_Skysphere
  2399. *
  2400. * INPUT
  2401. *
  2402. *   Vector - Translation vector
  2403. *
  2404. * OUTPUT
  2405. *
  2406. *   Skysphere - Pointer to skysphere structure
  2407. *
  2408. * RETURNS
  2409. *
  2410. * AUTHOR
  2411. *
  2412. *   Dieter Bayer
  2413. *
  2414. * DESCRIPTION
  2415. *
  2416. *   Translate a skysphere.
  2417. *
  2418. * CHANGES
  2419. *
  2420. *   Feb 1996 : Creation.
  2421. *
  2422. ******************************************************************************/
  2423.  
  2424. void Translate_Skysphere(Skysphere, Vector)
  2425. SKYSPHERE *Skysphere;
  2426. VECTOR Vector;
  2427. {
  2428.   TRANSFORM Trans;
  2429.  
  2430.   Compute_Translation_Transform(&Trans, Vector);
  2431.  
  2432.   Transform_Skysphere(Skysphere, &Trans);
  2433. }
  2434.  
  2435.  
  2436.  
  2437. /*****************************************************************************
  2438. *
  2439. * FUNCTION
  2440. *
  2441. *   Transform_Skysphere
  2442. *
  2443. * INPUT
  2444. *
  2445. *   Trans  - Pointer to transformation
  2446. *
  2447. * OUTPUT
  2448. *
  2449. *   Skysphere - Pointer to skysphere structure
  2450. *
  2451. * RETURNS
  2452. *
  2453. * AUTHOR
  2454. *
  2455. *   Dieter Bayer
  2456. *
  2457. * DESCRIPTION
  2458. *
  2459. *   Transform a skysphere.
  2460. *
  2461. * CHANGES
  2462. *
  2463. *   Feb 1996 : Creation.
  2464. *
  2465. ******************************************************************************/
  2466.  
  2467. void Transform_Skysphere(Skysphere, Trans)
  2468. SKYSPHERE *Skysphere;
  2469. TRANSFORM *Trans;
  2470. {
  2471.   if (Skysphere->Trans == NULL)
  2472.   {
  2473.     Skysphere->Trans = Create_Transform();
  2474.   }
  2475.  
  2476.   Compose_Transforms(Skysphere->Trans, Trans);
  2477. }
  2478.  
  2479.  
  2480.  
  2481.